package tools;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;

/**
 * Fonctions pour manipuler des fichiers.
 * @author Guillaume Poças
 */
public class FileUtils {

	/**
	 * Constructeur vide.
	 */
	public FileUtils(){	}
	
	/**
	 * Créer un fichier.
	 * @param path
	 */
	public final static void createFile(String path){
		try{ 
			File fichier = new File(path); 
			fichier.createNewFile(); // Cette fonction doit être appelée au sein d'un bloc TRY 
		} 
		catch (IOException e){ 
			System.out.println("Impossible de créer le fichier"); 
		}
	}
	
	/**
	 * Lister les fichiers d'un repertoire.
	 * @param directoryPath
	 * @return la liste des fichiers
	 */
	public final static File[] listFiles(String directoryPath){ 
		File[] files = null; 
		File directoryToScan = new File(directoryPath); 
		files = directoryToScan.listFiles();
		
		//Debug
		//for(File file : files) System.out.println("Fichier "+file.getName());
		
		return files; 
	}
	
	/**
	 * Supprimer un fichier.
	 * @param directoryPath
	 * @param fileName
	 * @return le fichier supprimé
	 */
	public final static File[] cleanFile(String directoryPath, String fileName){ 
		File[] files = null; 
		File directoryToScan = new File(directoryPath); 
		files = directoryToScan.listFiles();
		
		if(files.length != 0)
			for(File file : files)
				if(file.getName().equalsIgnoreCase(fileName))	file.delete();
		
		//Debug
		//for(File file : files) System.out.println("Fichier "+file.getName());
		
		return files; 
	}
	
	/**
	 * Supprime les fichiers d'un dossier.
	 * @param directoryPath
	 * @return les fichiers supprimés
	 */
	public final static File[] cleanDirectory(String directoryPath){ 
		File[] files = null; 
		File directoryToScan = new File(directoryPath); 
		files = directoryToScan.listFiles();
		
		if(files.length != 0)
			for(File file : files)
				file.delete();
		
		//Debug
		//for(File file : files) System.out.println("Fichier "+file.getName());
		
		return files; 
	} 
	
	/**
	 * Copie d'un fichier
	 * @param currentFile
	 * @param newFile
	 * @param bufferSize
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public final static void copyFileBuffered(final String currentFile, final String newFile, final int bufferSize) throws FileNotFoundException, IOException {  
        final BufferedReader in = new BufferedReader(new FileReader(currentFile), bufferSize * 1024);  
        try {  
            final BufferedWriter out = new BufferedWriter(new FileWriter(newFile), bufferSize * 1024);  
            try {  
                int s = in.read();  
                while(s != -1) {  
                    out.write(s);  
                    s = in.read();  
                }
                out.flush();  
              } finally {  
                out.close();  
            }
          } finally {  
            in.close();  
        }
    }
	
	/**
	 * Copie et chiffrement d'un fichier.
	 * Protocole Diffie-Hellmann.
	 * @param currentFile
	 * @param newFile
	 * @param bufferSize
	 * @param dh_key
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public final static void copyFileBufferedEncryptedDH(final String currentFile, final String newFile, final int bufferSize, String dh_key) throws FileNotFoundException, IOException {  
        final BufferedReader in = new BufferedReader(new FileReader(currentFile), bufferSize * 1024);
        byte[] key = dh_key.getBytes();
        int i = 0;
        try {  
            final BufferedWriter out = new BufferedWriter(new FileWriter(newFile), bufferSize * 1024);  
            try {  
                int s = in.read();
                int s_c = (s ^ key[i%dh_key.length()]);
                while(s != -1) {
                	i++;
                    out.write(s_c);  
                    s = in.read();
                    s_c = (s ^ key[i%dh_key.length()]);
                }
                out.flush();  
              } finally {  
                out.close();  
            }
          } finally {  
            in.close();  
        }
    }
	
	/**
	 * Envoi d'un fichier en TCP.
	 * @param socket
	 * @param originFile
	 * @param newFile
	 */
	public final static void tcpSendFile(Socket socket, String originFile, String newFile){
		byte buf[] = new byte[1024];
        int n, iter, cpt = 0;
        InputStream in = null;
        OutputStream out = null;
        
        File file = new File(originFile);
        
        try {
			in = new FileInputStream(file);
			out = socket.getOutputStream();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
        iter = (int)(file.length()/1024)+1;
        try {
			out.write(iter);
			System.out.println("Nbre Iter = "+iter);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
        
		System.out.println("Sending begin");
		try {
			while((n=in.read(buf))!=-1){
				System.out.println("Cpt = "+cpt+" et "+n);
			    out.write(buf,0,n);
			    out.flush();
			    cpt++;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("Sending end");
		
		try {
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Réception d'un fichier en TCP.
	 * @param socket
	 * @param path
	 */
	public final static void tcpWaitingFile(Socket socket, String path){
		byte buf[] = new byte[1024];
        int n = 0, iter = 0, cpt = 1;
        InputStream in = null;
        OutputStream out = null;
        
        try {
			in = socket.getInputStream();
			out = new FileOutputStream(path);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
        
        try {
			iter = in.read();
			System.out.println("Nbre Iter = "+iter);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
        
		System.out.println("Waiting begin");
		try {
			while(n != -1){
				n=in.read(buf);
				System.out.println("Cpt = "+cpt+" et "+n);
				if(n != 1024){
					System.out.println("Debug contenu paquet "+buf.toString());
					//byte buffer[] = new byte[1024];
					//buffer =("\n\nca bug ici!\n\n").getBytes(); 
					//out.write(buffer);
					//out.flush();
					if(iter != cpt)	iter++;
				}
				out.write(buf,0,n);
				out.flush();
			    cpt++;
			    if(iter == cpt){
			    	System.out.println("Dernière itération");
				    n=in.read(buf);
					System.out.println("Cpt = "+cpt+" et "+n);
					out.write(buf,0,n);
					out.flush();
					if(n != 1024) System.out.println("Debug contenu paquet "+buf.toString());
				    n = -1;
			    }
			    //cas d'une seule itération
			    else if(cpt > iter && iter == 1)	n = -1;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("Waiting end");
		
		try {
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Envoi de bytes en TCP.
	 * @param socket
	 * @param tab
	 * @throws IOException
	 */
	public final static void tcpSendBytes(Socket socket, byte[] tab) throws IOException {
		System.out.println("Sending begin");
		OutputStream out = socket.getOutputStream();
		out.write(ByteBuffer.allocate(4).putInt(tab.length).array());
		
		out.write(tab);
		out.flush();
		out.close();
		System.out.println("Sending end");
	}

	/**
	 * Réception de bytes en TCP.
	 * @param socket
	 * @throws IOException
	 */
	public final static void tcpWaitingBytes(Socket socket) throws IOException {
		System.out.println("Waiting begin");
		byte[] buf = new byte[4];
		InputStream in = socket.getInputStream();
		in.read(buf);
		int bufSize = ByteBuffer.wrap(buf).getInt();
		
		buf = new byte[bufSize];
		in.read(buf);
		in.close();
		System.out.println("Waiting end");
	}

}
